<script setup lang="ts" generic="P = any, D = any">
import { FormCreateItem } from '@/types/form-create';
import defu from 'defu';
import { ModalOptions } from 'naive-ui';

import QFormCreate from '../q-form-create/index.vue';
import { QFormCreateProps } from '../q-form-create/type';

const props = withDefaults(
	defineProps<{
		formItems: FormCreateItem[];
		api: (data: P) => Promise<D>;
		success?: (data: D) => void;
		modalOptions?: ModalOptions;
	}>(),
	{
		formItems: () => [],
		class: '',
	}
);

const emit = defineEmits<{
	(e: 'submit', values: any): void;
}>();

const title = ref('');

const createFormRef = ref<InstanceType<typeof QFormCreate>>();

const { message } = useFeedback(['message']);

const loading = ref(false);

const formItems = ref<FormCreateItem[]>(props.formItems);

const modalOptions = ref<ModalOptions>();
const showModal = ref(false);

const handleSubmit = async () => {
	loading.value = true;
	const data = createFormRef.value?.getValues() as P;
	try {
		const res = await props.api(data);
		props.success?.(res);
		showModal.value = false;
	} catch (error: any) {
		console.error(error);
		message.error(error.message);
	} finally {
		loading.value = false;
	}
};

const handleSave = () => {
	createFormRef.value?.validate((error) => {
		if (!error) {
			handleSubmit();
		}
	});
};

const handleCancel = () => {
	hide();
};

const show = (options: ModalOptions & { initialData?: Partial<P> }) => {
	showModal.value = true;
	title.value = `${options.title}`;
	modalOptions.value = defu(props.modalOptions, options);
	nextTick(() => {
		if (options?.initialData) {
			createFormRef.value?.setValues(options.initialData);
		}
	});
};

const hide = () => {
	showModal.value = false;
	createFormRef.value?.reset();
	modalOptions.value = undefined;
};

defineExpose({
	show,
	hide,
});
</script>

<template>
	<n-modal :class="cn('', modalOptions?.class)" v-model:show="showModal" preset="card" :title="title" v-bind="modalOptions">
		<q-form-create ref="createFormRef" :items="formItems">
			<template v-for="(slot, name) in $slots" #[name]="scope">
				<slot :name="name" v-bind="scope" />
			</template>
		</q-form-create>

		<template #footer>
			<div class="flex justify-end gap-4">
				<n-button @click="handleCancel"> 取消 </n-button>
				<n-button type="primary" @click="handleSave"> 保存 </n-button>
			</div>
		</template>
	</n-modal>
</template>
<style scoped></style>
